
import SQLite

class DbFriend : DbBase {
    var friend: Table = Table("friend")
    let _id = Expression<Int64>("id")
    let _userId = Expression<String>("userId")
    let _friendId = Expression<String>("friendId")
    let _alias = Expression<String>("alias")
    let _state = Expression<Int>("state")
    let _timestamp = Expression<Int64>("timestamp")
    let _userId_friendId = Expression<String>("_userId_friendId")
    
    func open(){
        do{
            try getDb()!.run(friend.create(ifNotExists: true) { t in
                t.column(_id, primaryKey: .autoincrement)
                t.column(_userId)
                t.column(_friendId)
                t.column(_alias)
                t.column(_state)
                t.column(_timestamp)
                t.column(_userId_friendId, unique: true)
            })
            try getDb()!.run(friend.createIndex(_userId, _friendId, unique: true, ifNotExists: true))

        }catch{
            print("\(error)")
        }
    }
    func toInfo(_ row:Row)->DMCCFriend{
        let u = DMCCFriend()
        u.id = row[_id]
        u.friendId = row[_friendId]
        u.userId = row[_userId]
        u.alias = row[_alias]
        u.timestamp = row[_timestamp]
        u.state = OsnFriendState(rawValue: row[_state])
        return u
    }
    func getFriendInfo(_ osnId:String) -> DMCCFriend? {
        do{
            for user in try getDb()!.prepare(friend.filter(osnId == _friendId)) {
                let fr = toInfo(user)
                return fr
            }
        }catch{
            print("\(error)")
        }
        return nil
    }
    func addFriendInfo(_ info:DMCCFriend) -> Bool {
        do{
            return try getDb()!.run(friend.upsert(
                _userId <- info.userId,
                _friendId <- info.friendId,
                _alias <- info.alias,
                _state <- info.state.rawValue,
                _timestamp <- info.timestamp,
                _userId_friendId <- info.userId+info.friendId,
                onConflictOf: _userId_friendId)) >= 0
        }catch{
            print("\(error)")
        }
        return false
    }
    func delFriendInfo(_ osnId:String) ->Bool {
        do{
            return try getDb()!.run(friend.filter(_friendId == osnId).delete()) > 0
        }catch{
            print("\(error)")
        }
        return false
    }
    func listFriendInfo() -> [DMCCFriend] {
        do{
            var list:[DMCCFriend] = []
            for friend in try getDb()!.prepare(friend) {
                let fr = toInfo(friend)
                list.append(fr)
            }
            return list
        }catch{
            print("\(error)")
        }
        return []
    }
    
    func listFriends(state:Int) -> [DMCCFriend] {
        do{
            var list:[DMCCFriend] = []
            for friend in try getDb()!.prepare(friend) {
                
                if toInfo(friend).state.rawValue == state {
                    list.append(toInfo(friend))
                }
            }
            return list
        }catch{
            print("\(error)")
        }
        return []
    }
}
let dbFriend = DbFriend()
